package com.bungarus.config;


import com.bungarus.Access;
import com.bungarus.busi.*;
import com.bungarus.codec.ProtobufWrappedWithHttpServerEncoder;
import com.bungarus.codec.UnwrapHttpReq2ProtobufDecoder;
import com.bungarus.codec.protobuf.MessageProtobuf;
import com.bungarus.codec.ssl.SSLEngineFactory;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;

import javax.net.ssl.SSLException;

/**
 * Created by tang on 2018/11/11.
 */
public class ChannelAccessInitializer extends ChannelServerInitializer {
    private final Access access;
    private final ServerAuthHandler serverAuthHandler;
    private final CreateSessionHandler createSessionHandler;
    private final TransferSessionHandler tranferSessionHandler;

    private final ClientMessageRequestHandler clientMessageReqHandler;
    private final ServerMediaHandler serverMediaHandler;
    private final AuthResponseHandler authResponseHandler;

    public ChannelAccessInitializer(Access access) {
        this.access = access;
        this.serverAuthHandler = new ServerAuthHandler(access);
        this.createSessionHandler = new CreateSessionHandler(access);
        this.tranferSessionHandler = new TransferSessionHandler(access);
        this.authResponseHandler = new AuthResponseHandler(access);
        this.clientMessageReqHandler = new ClientMessageRequestHandler(access);
        this.serverMediaHandler = new ServerMediaHandler();
    }

    @Override
    protected void initCodecHandlers(SocketChannel socketChannel) {
        if(Access.PORT_8080 == socketChannel.localAddress().getPort() ||
                Access.PORT_80 == socketChannel.localAddress().getPort()) {
            if(access.sslEnabled()) {
                try {
                    SslContext sslCtx = SslContextBuilder.forServer(SSLEngineFactory.getInstance().getKeyManagerFactory()).build();
                    socketChannel.pipeline().addLast("SSL", new SslHandler(sslCtx.newEngine(socketChannel.alloc())));
                } catch (SSLException e) {
                    e.printStackTrace();
                }
            }
            socketChannel.pipeline().addLast(new HttpServerCodec());
            socketChannel.pipeline().addLast(new HttpObjectAggregator(1024 * 1024));
            socketChannel.pipeline().addLast(new UnwrapHttpReq2ProtobufDecoder(MessageProtobuf.Message.getDefaultInstance()));
            socketChannel.pipeline().addLast(new ProtobufWrappedWithHttpServerEncoder());
            socketChannel.pipeline().addLast(new ProtobufEncoder());
        }
        else {
            super.initCodecHandlers(socketChannel);
        }
    }

    @Override
    protected void initNormalHandlers(SocketChannel socketChannel) {
        if(Access.PORT_8080 == socketChannel.localAddress().getPort() ||
                Access.PORT_80 == socketChannel.localAddress().getPort()) {
            socketChannel.pipeline().addLast(this.serverAuthHandler);
            socketChannel.pipeline().addLast(this.createSessionHandler);
            socketChannel.pipeline().addLast(this.tranferSessionHandler);
            socketChannel.pipeline().addLast(this.authResponseHandler);
            socketChannel.pipeline().addLast(this.clientMessageReqHandler);
        }
    }

    @Override
    protected void initServerServiceHandlers(SocketChannel socketChannel) {
        if(Access.PORT_7700 == socketChannel.localAddress().getPort() ||
                Access.PORT_7800 == socketChannel.localAddress().getPort()){
            socketChannel.pipeline().addLast(this.serverMediaHandler);
        }
    }
}
